#pragma once
#include <typescommon.h>

struct listNodeBase
{
    struct listNodeBase *frontn; // the front node pointer
    struct listNodeBase *nextn;  // the next node pointer
};

struct listNodeRoot
{
    struct listNodeBase *begin; // save the head node
    struct listNodeBase *end;   // save the end node
    uint32_t nodesize;
    pthread_mutex_t listlock;
};
int listRootInit(struct listNodeRoot *listroot);
int listRootFree(struct listNodeRoot *listroot);
int listRootSize(struct listNodeRoot *listroot);

enum listValueTypeEnum
{
    listValueType32 = 0,
    listValueType64,
    listValueTypeFloat,
    listValueTypeDouble,
    listValueTypeUser,
};
// list user node struct
struct listUsrNdStct
{
    struct listNodeBase node;
    uint32_t valtype;
    uint32_t valsize;
    char usrval[1];
};
#define listUsrNdHeadSize offsetof(struct listUsrNdStct, usrval)

// malloc space list user data.
struct listUsrNdStct *listUsrMlcSpc(uint32_t usertype, uint32_t userValueSize);
// list user malloc base type space
struct listUsrNdStct *listUsrMlc32(uint32_t setVal);
struct listUsrNdStct *listUsrMlc64(uint64_t setVal);
struct listUsrNdStct *listUsrMlcFloat(float setVal);
struct listUsrNdStct *listUsrMlcDouble(double setVal);


// list user push node into list root.
int listUsrPushNd(struct listNodeRoot *listroot, struct listUsrNdStct *unode, int optbackflag);
int listUsrPushBack(struct listNodeRoot *listroot, struct listUsrNdStct *unode);
int listUsrPushFront(struct listNodeRoot *listroot, struct listUsrNdStct *unode);

// list user pop node from list root.
struct listUsrNdStct *listUsrPopNd(struct listNodeRoot *listroot, int optbackflag);
struct listUsrNdStct *listUsrPopBack(struct listNodeRoot *listroot);
struct listUsrNdStct *listUsrPopFront(struct listNodeRoot *listroot);

// list user push back base type value
#define listUsrPsbk32(lroot, setVal) (listUsrPushBack(lroot, listUsrMlc32(setVal)))
#define listUsrPsfr32(lroot, setVal) (listUsrPushFront(lroot, listUsrMlc32(setVal)))
#define listUsrPsbk64(lroot, setVal) (listUsrPushBack(lroot, listUsrMlc64(setVal)))
#define listUsrPsfr64(lroot, setVal) (listUsrPushFront(lroot, listUsrMlc64(setVal)))
#define listUsrPsbkFlt(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcFloat(setVal)))
#define listUsrPsfrFlt(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcFloat(setVal)))
#define listUsrPsbkDbl(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcDouble(setVal)))
#define listUsrPsfrDbl(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcDouble(setVal)))

// get list user node pointer.
#define listUsrNdPtr(userNode, usrValType) ((usrValType *)(userNode->usrval))
